package com.arpa.oms.service.impl;

import cn.hutool.core.util.IdUtil;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.oms.domain.dto.OmsReceivableDetailDTO;
import com.arpa.oms.domain.entity.OmsReceivableDetail;
import com.arpa.oms.domain.vo.OmsReceivableDetailVO;
import com.arpa.oms.mapper.OmsReceivableDetailMapper;
import com.arpa.oms.service.IOmsReceivableDetailService;
import com.arpa.wms.common.util.BigDecimalUtil;
import com.arpa.wms.domain.dto.ExpenseDetailSettlementDTO;
import com.arpa.wms.domain.enums.ExpenseDetailStatusEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.Future;

/**
 * <p>
 * OMS应收明细 服务实现类
 * </p>
 *
 * @author LEO
 * @since 2020-11-17
 */
@Service
@Log4j2(topic = "business")
public class OmsReceivableDetailServiceImpl extends ServiceImpl<OmsReceivableDetailMapper, OmsReceivableDetail> implements IOmsReceivableDetailService {

    /**
     * 保存
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean save(OmsReceivableDetail entity) {
        if (StringUtils.isBlank(entity.getCode())) {
            entity.setCode(IdUtil.simpleUUID());
        }
        if (StringUtils.isBlank(entity.getCreatedBy())) {
            entity.setCreatedBy(UserUtil.getCode());
        }
        //设置金额类 保留两位小数四舍五入
        entity.setAmountMoney(BigDecimalUtil.getNumber(entity.getAmountMoney()));
        entity.setSettledMoney(BigDecimalUtil.getNumber(entity.getSettledMoney()));
        entity.setUnsettledMoney(BigDecimalUtil.getNumber(entity.getUnsettledMoney()));
        entity.setWaitingSettledMoney(BigDecimalUtil.getNumber(entity.getWaitingSettledMoney()));
        return super.save(entity);
    }

    /**
     * 根据code更新实体
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public int updateByCode(OmsReceivableDetail entity) {
        if (StringUtils.isBlank(entity.getModifiedBy())) {
            entity.setModifiedBy(UserUtil.getCode());
        }
        //设置金额类 保留两位小数四舍五入
        entity.setAmountMoney(BigDecimalUtil.getNumber(entity.getAmountMoney()));
        entity.setSettledMoney(BigDecimalUtil.getNumber(entity.getSettledMoney()));
        entity.setUnsettledMoney(BigDecimalUtil.getNumber(entity.getUnsettledMoney()));
        entity.setWaitingSettledMoney(BigDecimalUtil.getNumber(entity.getWaitingSettledMoney()));
        return baseMapper.update(entity, new QueryWrapper<OmsReceivableDetail>().lambda().eq(OmsReceivableDetail::getCode, entity.getCode()));
    }

    /**
     * 查询列表
     *
     * @param omsReceivableDetailDTO
     * @return
     */
    @Override
    public List<OmsReceivableDetailVO> queryList(OmsReceivableDetailDTO omsReceivableDetailDTO) {
        //排序字段名需要驼峰转数据库下划线类型字段名
        if (StringUtils.isNotEmpty(omsReceivableDetailDTO.getSortField())) {
            omsReceivableDetailDTO.setSortField(CommonUtil.camel2Underline(omsReceivableDetailDTO.getSortField()));
        }
        List<OmsReceivableDetailVO> omsReceivableDetailVOList = baseMapper.queryList(omsReceivableDetailDTO);
        return omsReceivableDetailVOList;
    }

    /**
     * 查询合计,包含总数
     *
     * @param omsReceivableDetailDTO
     * @return
     */
    @Override
    public OmsReceivableDetailVO queryListSum(OmsReceivableDetailDTO omsReceivableDetailDTO) {
        OmsReceivableDetailVO omsReceivableDetailVO = baseMapper.queryListSum(omsReceivableDetailDTO);
        return omsReceivableDetailVO;
    }


    @Async
    @Override
    public Future check(final ExpenseDetailSettlementDTO.SettlementItem settlementItem) {
        OmsReceivableDetail one = super.getOne(new QueryWrapper<OmsReceivableDetail>().lambda()
                .eq(OmsReceivableDetail::getCode, settlementItem.getCode())
        );
        if (null == one) {
            log.error("找不到费用明细。CODE【{}】", settlementItem.getCode());
            throw new ServiceException("找不到费用明细");
        }
        if (one.getStatus().equals(ExpenseDetailStatusEnum.SETTLED)) {
            log.error("已进行结算，不能重复结算。CODE【{}】", settlementItem.getCode());
            throw new ServiceException("已进行结算，不能重复结算");
        }
        if (settlementItem.getThisSettledMoney().compareTo(BigDecimal.ZERO) == 0) {
            log.error("结算金额【{}】不能等为0", settlementItem.getThisSettledMoney());
            throw new ServiceException("结算金额【{}】不能等为0");
        }
        BigDecimal temp = one.getAmountMoney().subtract(one.getSettledMoney()).subtract(one.getWaitingSettledMoney());
        if (settlementItem.getThisSettledMoney().abs().compareTo(temp.abs()) > 0) {
            log.error("本次结算金额【{}】不能超过未结算金额【{}】", settlementItem.getThisSettledMoney(), temp);
            throw new ServiceException("本次结算金额【" + settlementItem.getThisSettledMoney() + "】不能超过未结算金额【" + temp + "】");
        }
        return new AsyncResult(true);
    }

    /**
     * 生成结算单时更新费用金额
     *
     * @param code             费用明细标识
     * @param thisSettledMoney 本次结算金额
     * @param byCode           操作人code
     * @param name             操作人姓名
     */
    @Override
    public void updateSettlementMoney(String code, BigDecimal thisSettledMoney, String byCode, String name) {
        thisSettledMoney = BigDecimalUtil.getNumber(thisSettledMoney);
        baseMapper.updateSettlementMoney(code,thisSettledMoney,byCode,name);
    }

    /**
     * 删除、修改结算单后还原收费信息
     *
     * @param code                费用标识
     * @param restoreSettledMoney 要还原的金额
     */
    @Override
    public void restoreSettlementStatus(String code, BigDecimal restoreSettledMoney, BigDecimal amountReduce) {
        restoreSettledMoney = BigDecimalUtil.getNumber(restoreSettledMoney);
        amountReduce = BigDecimalUtil.getNumber(amountReduce);
        baseMapper.restoreSettlementStatus(code,restoreSettledMoney,amountReduce);
    }

    /**
     * 收款单审核通过后确认收费信息
     *
     * @param code         费用标识
     * @param confirmMoney 确认金额
     */
    @Override
    public void confirmSettlementStatus(String code, BigDecimal confirmMoney) {
        confirmMoney = BigDecimalUtil.getNumber(confirmMoney);
        baseMapper.confirmSettlementStatus(code,confirmMoney);
    }
}
